#include <stdio.h>
#include <stdlib.h>
#include "lwip/apps/httpd.h"
#include "lwip/apps/httpd_opts.h"
#include "lwip/def.h"
#include "lwip/apps/fs.h"
#include <string.h>
#include "httpd_fs.h"

typedef struct {
  httpd_fs_file *client;
  void *priv;
} httpd_fs_client;

static httpd_fs_file *g_http_file_head;

int fs_open_custom(struct fs_file *file, const char *name)
{
  httpd_fs_file *head = (httpd_fs_file *)g_http_file_head;

  file->pextension = NULL;
  while(head) {
    if (head->name && (strcmp(name, head->name) == 0)) {
      httpd_fs_client *info = (httpd_fs_client *)malloc(sizeof(httpd_fs_client));
      info->priv = NULL;
      info->client = head;
      file->pextension = info;
      return head->open(file, name, &info->priv);
    }
    head = (httpd_fs_file *)head->next;
  }
  head = (httpd_fs_file *)g_http_file_head;
  while(head) {
    if (head->name == 0) {
      int ret;
      void *priv = NULL;

      ret = head->open(file, name, &priv);
      if (ret) {
        httpd_fs_client *info = (httpd_fs_client *)malloc(sizeof(httpd_fs_client));
        info->priv = priv;
        info->client = head;
        file->pextension = info;
        return ret;
      }
      return 0;
    }
    head = (httpd_fs_file *)head->next;
  }
  return 0;
}

void fs_close_custom(struct fs_file *file)
{
  httpd_fs_client *client = (httpd_fs_client *)file->pextension;

  if (client && client->client && client->client->close) {
    client->client->close(file, &client->priv);
    free(client);
    return;
  }
  if (file->data) {
    free((void *)file->data);
    file->data = NULL;
  }
  free(client);
}

int fs_read_custom(struct fs_file *file, char *buffer, int count)
{
  httpd_fs_client *client = (httpd_fs_client *)file->pextension;

  if (client && client->client && client->client->read) {
    return client->client->read(file, buffer, count, &client->priv);
  }
  return 0;
}

void httpd_fs_add_file(httpd_fs_file *file, const char *name, 
        int (*open)(struct fs_file *file, const char *name, void **priv),
        int (*read)(struct fs_file *file, char *buffer, int count, void **priv),
        int (*write)(struct fs_file *file, const char *buffer, int count, void **priv),
        void (*close)(struct fs_file *file, void **priv))
{
    file->name = name;
    file->open = open;
    file->read = read;
    file->write = write;
    file->close = close;
    file->next = g_http_file_head;
    g_http_file_head = file;
}
